package com.da.javatest.interview.session3;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author JokerDa.
 * @date 2020/12/27 14:14
 * Description:
 * 可重入锁：可重复递归调用的锁，在外层获取了锁之后，在内层仍然可以直接使用，并且不发生死锁，这样的锁就叫可重入锁
 */
public class Test03ReEnterLock {
    private static final Object lockA = new Object();
    private static final Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        //m1();
        //m2();
        m5();
    }

    private static void m1() {
        new Thread(() -> {
            synchronized (lockA) {
                System.out.println(Thread.currentThread().getName() + " ------>" + "外层调用");
                synchronized (lockA) {
                    System.out.println(Thread.currentThread().getName() + " ------>" + "中层调用");
                    synchronized (lockA) {
                        System.out.println(Thread.currentThread().getName() + " ------>" + "内层调用");
                    }
                }
            }
        }).start();
    }

    private synchronized static void m2() {
        System.out.println("外层调用");
        m3();
    }

    private synchronized static void m3() {
        System.out.println("中层调用");
        m4();
    }

    private synchronized static void m4() {
        System.out.println("内层调用");
    }

    /**
     * 加锁和解锁的次数必须一样 不然会死锁别人
     */
    private static void m5() {
        new Thread(() -> {
            try {
                lock.lock();
                lock.lock();
                System.out.println("外层调用");
                try {
                    lock.lock();
                    System.out.println("内层调用");
                } finally {
                    lock.unlock();
                }
            } finally {
                lock.unlock();
                //lock.unlock();
            }

        }).start();

        new Thread(() -> {
            try {
                lock.lock();
                System.out.println("t2调用");
            } finally {
                lock.unlock();
            }

        }).start();
    }
}
